/**
 *  Copyright (C) 2006 zhangbo (freeeob@gmail.com)
 *
 *  This product is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2.1 of the License, or
 *  (at your option) any later version.
 * 
 *  This product is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 *
 *  author:zhangbo
 *  Email:jsjava@gmail.com
 */

/**  The Complex class references to org.apache.commons.math.complex.ComplexUtils */

function ComplexUtils(){
	this.jsjava_class="org.apache.commons.math.complex.ComplexUtils";
}

/**
 * Compute the inverse cosine for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.acos=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }

    return Complex.I.negate().multiply(ComplexUtils.log(z.add(
        Complex.I.multiply(ComplexUtils.sqrt1z(z))))); 
};

/**
 * Compute the inverse sine for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.asin=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }

    return Complex.I.negate().multiply(ComplexUtils.log(ComplexUtils.sqrt1z(z).add(
        Complex.I.multiply(z))));
};

/**
 * Compute the inverse tangent for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.atan=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    return Complex.I.multiply(
        ComplexUtils.log(Complex.I.add(z).divide(Complex.I.subtract(z))))
        .divide(new Complex(2.0, 0.0));
};

/**
 * Compute the cosine for the given complex argument.
 * @param z a complex number 
 */
ComplexUtils.cos=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a = z.getReal();
    var b = z.getImaginary();
    
    return new Complex(Math.cos(a) * MathUtils.cosh(b),
        -Math.sin(a) * MathUtils.sinh(b));
};

/**
 * Compute the hyperbolic cosine for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.cosh=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a = z.getReal();
    var b = z.getImaginary();
    
    return new Complex(MathUtils.cosh(a) * Math.cos(b),
        MathUtils.sinh(a) * Math.sin(b));
};

/**
 * Compute the exponential function for the given complex argument.
 * @param z  a complex number
 */
ComplexUtils.exp=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var b = z.getImaginary();
    var expA = Math.exp(z.getReal());
    return new Complex(expA *  Math.cos(b), expA * Math.sin(b));
};

/**
 * Compute the natural logarithm for the given complex argument. 
 * @param z a complex number
 */
ComplexUtils.log=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }

    return new Complex(Math.log(z.abs()),
        Math.atan2(z.getImaginary(), z.getReal())); 
};

/**
 * Creates a complex number from the given polar representation.
 * @param r the modulus of the complex number to create
 * @param theta the argument of the complex number to create
 */
ComplexUtils.polar2Complex=function(r,theta){
	if (r < 0) {
        throw new IllegalArgumentException
            (IllegalArgumentException.ERROR,"Complex modulus must not be negative");
    }
    return new Complex(r * Math.cos(theta), r * Math.sin(theta));
};

/**
 * Returns of value of y raised to the power of x.
 * @param y a complex number
 * @param x a complex number
 */
ComplexUtils.pow=function(y,x){
	return ComplexUtils.exp(x.multiply(ComplexUtils.log(y)));
};

/**
 * Compute the sine for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.sin=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a = z.getReal();
    var b = z.getImaginary();
    
    return new Complex(Math.sin(a) * MathUtils.cosh(b),
        Math.cos(a) * MathUtils.sinh(b));
};

/**
 * Compute the hyperbolic sine for the given complex argument.
 * @param z a complex number 
 */
ComplexUtils.sinh=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a = z.getReal();
    var b = z.getImaginary();
    
    return new Complex(MathUtils.sinh(a) * Math.cos(b),
        MathUtils.cosh(a) * Math.sin(b));
};

/**
 * Compute the square root for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.sqrt=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a = z.getReal();
    var b = z.getImaginary();
    
    var t = Math.sqrt((Math.abs(a) + z.abs()) / 2.0);
    if (a >= 0.0) {
        return new Complex(t, b / (2.0 * t));
    } else {
        return new Complex(Math.abs(b) / (2.0 * t),
            MathUtils.indicator(b) * t);
    }
};

/**
 * Compute the square root of 1 - z2 for the given complex argument.
 * @param z a complex number 
 */
ComplexUtils.sqrt1z=function(z){
	return ComplexUtils.sqrt(Complex.ONE.subtract(z.multiply(z)));
};

/**
 * Compute the tangent for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.tan=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a2 = 2.0 * z.getReal();
    var b2 = 2.0 * z.getImaginary();
    var d = Math.cos(a2) + MathUtils.cosh(b2);
    
    return new Complex(Math.sin(a2) / d, MathUtils.sinh(b2) / d);
};

/**
 * Compute the hyperbolic tangent for the given complex argument.
 * @param z a complex number
 */
ComplexUtils.tanh=function(z){
	if (z.isNaN()) {
        return Complex.NaN;
    }
    
    var a2 = 2.0 * z.getReal();
    var b2 = 2.0 * z.getImaginary();
    var d = MathUtils.cosh(a2) + Math.cos(b2);
    
    return new Complex(MathUtils.sinh(a2) / d, Math.sin(b2) / d);
};